package com.seaengine.net
{
	
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	/**
	 * packet int32 型协议, 且发送有队列。 
	 * @author yangqx
	 * 
	 */
	public class Int32QueueProtocol extends TCPProtocol/*  implements IProtocol */
	{
		protected var _currentMessage:int;
		
		protected var _taskQueue:TaskQueue	= new TaskQueue();
		
		protected var _reConnector:Timer 	= new Timer(60000);
		
		private const CONNECT_OVER_TIME:int	= 5;
		
		private var _connectCount:int		= 0;
		
		private var _streamBuffer:JoyPortBuffer  ;
		
				
		public function Int32QueueProtocol(host:String=null, port:int=0)
		{
			super(host, port);
			_taskQueue.bind(this,send,JoyPortBuffer);
			addEventListener(ProtocolEvent.CONNECT_OVER_TIME,onConnectOverTimer);
			_taskQueue.addEventListener(TaskEvent.TASK_DONE,onTaskDone);
			_taskQueue.addEventListener(TaskEvent.TASK_OVER_TIME,onTaskOverTime);
			_reConnector.addEventListener(TimerEvent.TIMER,onReConnect);
		}
		
		/**
		 * 
		 * 
		 */
		public function stop():void
		{
			if(connected)
			{
				close();
			}
			if(_reConnector.running)
			{
				_reConnector.stop();
			}
			_taskQueue.removeAllTask();
		}
		
		private function onReConnect(e:TimerEvent):void
		{			
			if(_connectCount > CONNECT_OVER_TIME)
			{
				var event:ProtocolEvent = new ProtocolEvent(ProtocolEvent.CONNECT_OVER_TIME);
				event.scene	= this.toString();
				dispatchEvent(event);
				return;
			}
			try{
				if(host && port)
				{
					connect(host,port);
				}
			}catch(err:Error){
				++_connectCount;
			}
		}
		
		private function onConnectOverTimer(e:ProtocolEvent):void
		{
			stop();
		}
		
		private function onTaskOverTime(e:TaskEvent):void
		{
			dispatchEvent(new ProtocolEvent(ProtocolEvent.NET_WORK_OVER_TIME));   //这里网络循环超时了，应该终止网络
		}
		
		protected function onTaskDone(e:TaskEvent):void
		{
			_taskQueue.isRun = false;
		}
		
		override protected function connectHandler(e:Event):void
		{
			super.connectHandler(e);
			if(_reConnector.running)
			{
				_reConnector.stop();
				_connectCount = 0;
			}
			if(_taskQueue.hasTask && !_taskQueue.isRun)
			{
				_taskQueue.start();
			}
		}
		
		override protected function dataHandler(e:ProgressEvent):void
		{
			super.dataHandler(e);
			var data:JoyPortBuffer = new JoyPortBuffer();
			while(bytesAvailable)
			{
				this.readBytes(data);
				if( _streamBuffer)
					_streamBuffer.append(data);
				else
					_streamBuffer = data;
			}
			onReceivedData(_streamBuffer);
		}
		 
		private function onReceivedData(data:JoyPortBuffer):void
		{
			var integrityLength:int = checkStream(data);
			if ( integrityLength)
			{
				data.seek();
				onReceivedIntegrityData(data.truncateBuffer(0,integrityLength));
				
				if( data.length > integrityLength)
				{
					//trace("粘包");
					var remainData:JoyPortBuffer = data.truncateBuffer(integrityLength,data.length - integrityLength);
					onReceivedData(remainData);
				}else
				{
					_streamBuffer = null;
				}
			}
		}
		
		override protected function errorHandler(e:IOErrorEvent):void
		{
			super.errorHandler(e);
			if(!_reConnector.running)
			{
				_reConnector.start();
			}
		}
		
		protected function onReceivedIntegrityData(data:JoyPortBuffer):void
		{
			//trace("Integrity Data Length :" , data.length);
		}
		
		override protected function send(buffer:JoyPortBuffer, len:uint=0, offset:uint=0):void
		{
			if(!connected  || _taskQueue.isRun )
			{
				_taskQueue.addTask(buffer);
				return;
			}
			try{
				super.send(buffer,len,offset);
				var es:TaskEvent = new TaskEvent(TaskEvent.TASK_SUCCEED);
				dispatchEvent(es);
			}catch(err:Error){
				var ef:TaskEvent = new TaskEvent(TaskEvent.TASK_FAIL);
				ef.reason 		= err.message;
				dispatchEvent(ef);
			}
		}
		
		private function checkStream(buffer:JoyPortBuffer):int
		{
			buffer.position = 8;
			var packageLength:int = buffer.readShort();
			if(buffer.length < (packageLength + 12) || !packageLength)
			{
				buffer.position = 0;
				_streamBuffer = buffer;
				return 0;
			}
			return packageLength + 12;
		}
		
		override public function close() : void
		{
			_streamBuffer = null;
			try
			{
				super.close();
			}catch(e:Error){
				
			}
		}
	}
}